package com.project.restaurant.common.util;

import com.project.restaurant.common.annotation.CopyProperty;
import com.project.restaurant.common.bean.FieldWrapper;
import org.reflections.ReflectionUtils;
import org.springframework.beans.BeanUtils;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class CopyPropertiesUtils {

    public static void copyProperties(Object source,Object target) throws Exception {
        Set<Field> sourceAllFields = ReflectionUtils.getAllFields(source.getClass());
        Map<String, FieldWrapper> map = getAllFieldMap(target);
        for(Field field:sourceAllFields){
            field.setAccessible(true);
            boolean find = false;
            FieldWrapper fieldWrapper = map.get(field.getName());
            if(fieldWrapper!=null){
                Object fieldValue = getFieldValue(fieldWrapper, target);
                if(fieldValue!=null && field.getType() == fieldValue.getClass()){
                    field.set(source,fieldValue);
                    find = true;
                }
            }
            CopyProperty copyProperty = field.getAnnotation(CopyProperty.class);
            if(!find && copyProperty!=null){
                String[] alias = copyProperty.alias();
                for(String filedName:alias){
                    Object fieldValue = findFieldValue(map, target, filedName.split("\\."), 0);
                    if(fieldValue!=null && field.getType() == fieldValue.getClass()){
                        field.set(source,fieldValue);
                        find = true;
                    }
                }
            }
        }
    }

    public static Object findFieldValue(Map<String, FieldWrapper> map, Object obj,String[] fieldLevelNames, int now) throws Exception {
        FieldWrapper wrapper = map.get(fieldLevelNames[now]);
        if(now+1 >= fieldLevelNames.length){
            return getFieldValue(wrapper,obj);
        }
        Class fieldClass;
        //不存在该联级字段，停止递归。或者该字段类型是简单类型
        if( (wrapper!=null && BeanUtils.isSimpleProperty(fieldClass = wrapper.getField().getType())) || wrapper==null ){
            return null;
        }
        //说明该字段是复杂类型属性
        Map<String, FieldWrapper> lazyChildWrapper = wrapper.getChildFieldMap();
        //可能在中间就存在对象属性为null的情况
        Object fieldValue = getFieldValue(wrapper, obj);
        if(fieldValue==null){
            return null;
        }
        //如果该字段里的所有属性都加载过了，即不为null，则对该字段的子字段进行递归查找
        if (lazyChildWrapper==null){
            //否则进行懒加载
            lazyChildWrapper = getAllFieldMap(fieldValue);
            wrapper.setChildFieldMap(lazyChildWrapper);
        }
        return findFieldValue(lazyChildWrapper,fieldValue,fieldLevelNames,now+1);
    }
    public static Object getFieldValue(FieldWrapper fieldWrapper,Object obj){
        if(fieldWrapper==null){
            return null;
        }
        Field field = fieldWrapper.getField();
        field.setAccessible(true);
        try {
            return field.get(fieldWrapper.getObj());
        } catch (IllegalAccessException e) {
            System.out.print(String.format("在%s里找不到字段%s", obj.toString(),field.getName()));
            return null;
        }
    }

    public static Map<String, FieldWrapper> getAllFieldMap(Object obj){
        //如果是简单类型，则返回null，因为简单类型，应该认为它是没有属性的
        if(BeanUtils.isSimpleProperty(obj.getClass())){
            return null;
        }
        return  ReflectionUtils.getAllFields(obj.getClass())
                .stream()
                .collect(Collectors.toMap(Field::getName, field-> new FieldWrapper(obj,field,null)));
    }
}
